#ifndef __G_TASK_MANAGER_H__
#define __G_TASK_MANAGER_h__

#include <vector>

#include "GTypes.h"
#include "GSingleton.h"
#include "GTaskResult.h"
#include "GWorkerThread.h"
#include "GInitializable.h"

#include "GSemaphore.h"

#define G_MULTI_THREADING_ENABLED

namespace GThread { class GEvent; }

namespace GEngine
{
	class GTask;
	class GTaskQueue;

	class GTaskManager : public GUtil::GInitializable, public GUtil::GSingleton<GTaskManager>
	{
	friend class GUtil::GSingleton<GTaskManager>;
	
	typedef volatile GTaskResult ResultType; //! get rid of volatile

	typedef std::atomic_bool AtomicBool;
	typedef std::vector<GTaskQueue*> QueueArrType;
	typedef std::vector<GWorkerThread*> WorkerArrType;
	typedef std::vector<GThread::GEvent*> EventArrType;
	typedef GThread::GSemaphore Semaphore;

	protected:
		QueueArrType	Queues;

		WorkerArrType	Workers;
		GSize			WorkerCount;

		ResultType*		RootResult;

		EventArrType	IdleEvents;
		Semaphore		ActiveSemaphore;

		AtomicBool		Exiting;

						GTaskManager();
						~GTaskManager();

		void			WaitAllWorkers();
		void			ExitAllWorkers();
		void			WakeAllWorkers();

	public:
		bool			CheckExiting();
		bool			CheckRootComplete();

		GSize			GetWorkerCount() const;

		bool			Schedule(GTask* Task, GSize ThreadId = mGCurrentWorkerId);
		bool			ScheduleRoot(GTask* Task);

		void			BusyWait(GTaskResult* Result);

		bool			Initialize() OVERRIDE;
		void			Uninitialize() OVERRIDE;
	};
}

#define mGTaskManager	GEngine::GTaskManager::GetInstance()

#endif